<?php

namespace App\Models;

use App\Exceptions\CustomException;
use App\Http\Controllers\Api\MiniProgramController;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * App\Models\Order
 *
 * @property int $id
 * @property string $no 订单编号
 * @property int $product_id 商品id
 * @property int $sku_id 商品规格id
 * @property float $sold_price 购买时单价。商品价格有可能会改变。
 * @property float $origin_price 原价
 * @property int $num 购买数量
 * @property int|null $total_money 总金额，单位为分。
 * @property int|null $cash_money 现金支付金额
 * @property int $user_id
 * @property string $openid
 * @property string $username
 * @property string $mobile
 * @property string|null $address 收货地址
 * @property string|null $remark 备注
 * @property string $payment_method 支付方式
 * @property string|null $prepay_id 预付单信息
 * @property string|null $transaction_id 微信支付单号
 * @property string|null $delivery 物流单号
 * @property string $status 订单状态：-1：未支付；0：已支付；1：已使用；2：已发货。
 * @property array|null $snapshoot 订单快照
 * @property string|null $time_end 支付完成时间
 * @property string|null $rebate_status 分润。0：未分润；1：已分润。
 * @property string|null $mp_code 订单小程序码
 * @property Carbon|null $created_at
 * @property Carbon|null $updated_at
 * @property Carbon|null $deleted_at
 * @property string|null $used_at
 * @property-read Product $product
 * @property-read Collection|Rebate[] $rebates
 * @property-read int|null $rebates_count
 * @property-read ProductSku $sku
 * @property-read User $user
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order newQuery()
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Order onlyTrashed()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order query()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereAddress($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereCashFee($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereDeletedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereDelivery($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereMobile($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereMpCode($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereNo($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereNum($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereOpenid($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereOriginPrice($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order wherePaymentMethod($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order wherePrepayId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereProductId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereRebateStatus($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereRemark($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereSkuId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereSnapshoot($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereSoldPrice($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereStatus($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereTimeEnd($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereTotalFee($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereTransactionId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereUpdatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereUsedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereUserId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order whereUsername($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Order withTrashed()
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Order withoutTrashed()
 * @mixin Eloquent
 */
class Order extends Model
{
    use SoftDeletes;
    protected $fillable = [
        'no','product_id','product_sku_id','num','origin_price','sold_price','user_id','mobile','delivery','username',
        'remark','snapshoot','address','prepay_id','total_money', 'cash_money', 'openid','rebate_status','mp_code',
        'address_id', 'template_message_sent_at'
    ];
    protected $casts = ['snapshoot' => 'json'];

    protected static function boot()
    {
        parent::boot();
        //登录的如果是商家账号，则只能查询自己商铺的商品
        static::addGlobalScope('store_order',function (Builder $builder){
            if ($admin = Auth::user()) {//后台登录
                //todo  当前登录用户只要有商铺，就给添加查询作用域
                if ($admin->hasRole('shop')) {
                    $store_id = Store::where('admin_id',Auth::user()->id)->value('id');
                    $product_ids = Product::where('store_id',$store_id)->pluck('id')->toArray();
                    $builder->whereIn('product_id',$product_ids);
                }
            }
        });
    }


    //订单所属用户
    public function user() {
        return $this->belongsTo('App\Models\User');
    }
    //返回订单列表数据
    public function get_orders($where = [],$limit){
        //查询订单
        $orders = $this->where($where)->orderBy('id','desc')->paginate($limit)->toArray();
        //return $orders;
        //提取订单id数组
        $order_ids = array_column($orders['data'], 'id');
        //return $order_ids;
        //查询订单的商品
        $order_products = OrderProduct::leftJoin('products','products.id', '=', 'order_products.product_id')
                                        ->leftJoin('product_skus','product_skus.id', '=', 'order_products.sku_id')
                                        ->whereIn('order_id', $order_ids)
                                        ->select('order_products.*', 'products.cover', 'products.title as product_title', 'product_skus.title as sku_title')
                                        ->get()->toArray();

        foreach ($orders['data'] as &$order) {
            foreach ($order_products as $product) {
                if ($order['id'] == $product['order_id']) {
                    $order['products'][] = $product;
                }
            }
        }
        return $orders;
    }


    //订单详情
    public function order_info($order_id, $user_id) {
        return $this->where('id', $order_id)->where('user_id', $user_id)->first();
    }


    /**
     * 创建订单初始化
     * @param array $request_data
     * @return array
     * @throws CustomException
     */
    public function create_order_init(array $request_data) {
        $products = [];
        $total_money = 0;
        $user_model = new User();
        $user = $user_model->get_login_user($request_data['api_token']);

        $product_model = new Product();

        if ($request_data['type'] == 'cart') {//购物车
            $cart_ids = array_column($request_data['carts'], 'cart_id');
            $cart_model = new Cart();
            $carts = $cart_model->carts($user->id, $cart_ids);

            if (count($carts) == 0) {
                throw new CustomException("购物车不存在");
            }
            $products = $product_model->get_products_by_cart_ids($cart_ids, $user->id);

            //计算总价
            foreach ($request_data['carts'] as $cart) {
                foreach ($products as &$product) {
                    if ($cart['cart_id'] == $product->cart_id) {
                        $total_money = bcadd($total_money, $product->sold_price * $cart['buynum'], 2);
                        $product->buynum = $cart['buynum'];
                    }
                }
            }
        }elseif ($request_data['type'] == 'product') {
            $product = $product_model->get_product_sku($request_data['product']['product_id'], $request_data['product']['sku_id']);

            $total_money = bcadd($total_money, $product->sold_price * $request_data['product']['buynum'], 2);
            $product->buynum = $request_data['product']['buynum'];

            $products[] = $product;
        }elseif ($request_data['type'] == 'order') {
            $order = $this->order_info($request_data['order_id'], $user->id);
            if (!$order) {
                throw new CustomException("订单不存在");
            }
            $products = $product_model->get_products_by_order_id($order->id);
            $total_money = $order->total_money;
        }
        //添加下单数量*
        // $product = Product::find($request_data['product']['product_id']);
        // $product->score = $product->score + $request_data['product']['buynum'];
        // $product->save();

        return ['list' => $products, 'total_money' => $total_money];
    }

    /**
     * 支付订单
     * @param array $request_data
     * @param $client_ip
     * @return mixed
     * @throws GuzzleException
     * @throws \Exception
     */
    public function do_cash(array $request_data, $client_ip) {
//        DB::beginTransaction(function () use ($request_data, $client_ip) {
            $api_token = $request_data['api_token'];
            $user_model = new User();
            $user = $user_model->get_login_user($api_token);

            $type = $request_data['type'];
            $request_product = $request_data['product'] ?? [];
            $carts = $request_data['carts'] ?? [];
            $order_id = $request_data['order_id'] ?? null;
            $remark = $request_data['remark'] ?? '';
            $request_total_money = $request_data['total_money'] ?? 0;
            $address_id = $request_data['address_id'] ?? 0;

            $product_model = new Product();
            $total_money = $cash_money = 0;
            $products = [];
            $order_no = '';
            //查询商品信息并计算总价
            switch ($type) {
                case 'cart':    //支付购物车
                    $cart_ids = array_column($carts, 'cart_id');
                    $cart_model = new Cart();
                    $carts = $cart_model->carts($user->id, $cart_ids);

                    if (count($carts) == 0) {
                        throw new CustomException("购物车不存在");
                    }
                    $products = $product_model->get_products_by_cart_ids($cart_ids, $user->id);
                    //计算总价
                    foreach ($request_data['carts'] as  $k=>$cart) {
                        foreach ($products as &$product) {
                            if ($cart['cart_id'] == $product->cart_id) {
                                $total_money = bcadd($total_money, $product->sold_price * $cart['buynum'], 2);
                                $product->buynum = $cart['buynum'];
                            }
                        }
                    }
                    if (bccomp($total_money, $request_total_money) !== 0) {
                        throw new CustomException( '商品价格有变动，请刷新后重新提交');
                    }
                    //删除购物车
                    Cart::whereIn('id', $cart_ids)->delete();
                    break;
                case 'product': //支付商品  todo    扣减库存
                    $product = $product_model->get_product_sku($request_product['product_id'], $request_product['sku_id']);
                    //判断库存
                    if (bccomp($request_product['buynum'], $product->stock) === 1) {
                        throw new CustomException('的商品库存不足');
                    }
                    $total_money = bcadd($total_money, $product->sold_price * $request_product['buynum'], 2);
                    if (bccomp($total_money, $request_total_money) !== 0) {
                        throw new CustomException( '商品价格有变动，请刷新后重新提交');
                    }
                    $product->buynum = $request_product['buynum'];
                    $products[] = $product;
                    break;
                case 'order':
                    //查询订单
                    $order = $this->order_info($order_id, $user->id);
                    if (!$order) {
                        throw new CustomException('订单不存在');
                    }
                    $order_no = $order->no;
                    $total_money = $order->total_money;
                    break;
                default :
                    throw new CustomException("数据错误");
            }

            if ($type == 'order') {
                //存在收货人、电话、地址、备注时修更新定单的该信息
                $update_data = [];
                $address_id ? $update_data['address_id'] = $address_id : '';
                $remark ? $update_data['remark'] = $remark : '';
                if ($update_data) {
                    Order::where('id',$order_id)->update($update_data);
                }
            }else {
                $order_no = date('Ymd') . $user['id'] . rand(1,1000);
                //插入一条待支付订单
                $insert_order_data = [
                    'no'                =>  $order_no,
                    //订单总金额单位为分
                    'total_money'       =>  $total_money,
                    //现金支付金额，可能会有优惠券。
                    'cash_money'        =>  $total_money,
                    'user_id'           =>  $user->id,
                    'remark'            =>  $remark,
                    'address_id'        =>  $address_id,
                    'openid'            =>  $user->openid,
                    'snapshoot'         =>  $products
                ];

                //dd($insert_order_data);

                $order = Order::create($insert_order_data);

                //3、订单商品表插入数据
                $insert_order_products_data = [];
                foreach ($products as $item) {
                    $insert_order_products_data[] = [
                        'order_id'      =>  $order->id,
                        'product_id'    =>  $item->product_id,
                        'sku_id'        =>  $item->sku_id,
                        'origin_price'  =>  $item->origin_price,
                        'sold_price'    =>  $item->sold_price,
                        'buynum'        =>  $item->buynum
                    ];
                }
                DB::table("order_products")->insert($insert_order_products_data);
                //3、流水表插入订单记录
                Flow::create([
                    'money'         =>  $total_money,
                    'type'          =>  ORDER,
                    'user_id'       =>  $user->id,
                    'business_id'   =>  $order->id
                ]);
            }

            //商品描述
            $body = '商品的描述';

            //以后会有优惠券
            $cash_money = $total_money;
            //4、调用支付统一下单，返回预支付交易会话结果
            $mp_controller = new MiniProgramController();
            $prepay_info = $mp_controller->unifiedorder($body, $order_no, $cash_money * 100, $client_ip, $user->openid);

            if($prepay_info) {
                //更新微信支付返回的订单号
                Order::where('id',$order->id)->update(['prepay_id' => $prepay_info['prepay_id']]);
                unset($prepay_info['appid'],$prepay_info['prepay_id']);
                return $prepay_info;
            }else {
                throw new CustomException('支付失败');
            }
//        });
    }

    /**
     * 分组查询订单数量
     * @param $user_id
     * @return mixed
     */
    public function order_num_by_group($user_id) {
        return $this
                ->select(DB::raw('count(*) as num, status'))
                ->where('user_id', $user_id)
                ->groupBy('status')
                ->orderBy('status')
                ->get()
                ->toArray();
    }

    public function order_products() {
        return $this->hasMany("App\Models\OrderProduct");
    }

    public function address() {
        return $this->belongsTo("App\Models\Address");
    }

    public function detail($order_id, $user_id) {
        $order = $this->order_info($order_id, $user_id)->toArray();
        //查询订单的商品
        $order_products = OrderProduct::leftJoin('products','products.id', '=', 'order_products.product_id')
                                        ->leftJoin('product_skus','product_skus.id', '=', 'order_products.sku_id')
                                        ->where('order_id', $order_id)
                                        ->select('order_products.*', 'products.cover', 'products.title as product_title', 'product_skus.title as sku_title')
                                        ->get()->toArray();
        $order['products'] = $order_products;
        return $order;
    }

    /**
     * 确认收货
     * @param $order_id
     * @param $user_id
     * @return bool
     */
    public function receive($order_id, $user_id) {
        Order::where([
            'id'        =>  $order_id,
            'user_id'   =>  $user_id,
            'status'    =>  TO_SIGN
        ])->update(['status' => TO_COMMENT]);

        return true;
    }

    /**
     * 评价订单
     * @param $order_id
     * @param $user_id
     * @param $content
     * @return bool
     */
    public function comment($order_id, $user_id, $content) {
        OrderComment::firstOrCreate([
            'order_id'  =>  $order_id,
            'content'   =>  $content,
        ]);

        Order::where([
            'id'        =>  $order_id,
            'user_id'   =>  $user_id,
        ])->update(['status' => COMMENT]);
        return true;
    }

    /**
     * @return array
     * 订单统计
     */
    public function getOrderNumber()
    {
        $noPayNumber = Order::whereDate('created_at',date("Y-m-d"))->where('status',1)->count();//未付款订单
        $hasPayNumber = Order::whereDate('created_at',date("Y-m-d"))->where('status',2)->count();//已付款订单
        $hasPayMoney = Order::whereDate('created_at',date("Y-m-d"))->where('status',2)->sum('cash_money');//已付款金额
        $totalNumber = Order::where('status',2)->count();//总订单数量
        $todaySendOut = Order::whereDate('created_at',date("Y-m-d"))->where('status',3)->sum('cash_money');//已付款金额
        $totalSendOut = Order::where('status',3)->count();//总订单数量
        $totalMoney = Order::whereDate('created_at',date("Y-m-d"))->where('status',2)->sum('cash_money');//累计收入
        return ['noPay'=>$noPayNumber,'hasPayOrder'=>$hasPayNumber,'hasPayMoney'=>$hasPayMoney,'totalNumber'=>$totalNumber,'totalMoney'=>$totalMoney,'todaySendOut'=>$todaySendOut,'totalSendOut'=>$totalSendOut];
    }

}
